package com.df.blueben.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.df.blueben.AiClient.TagsSelectAi;
import com.df.blueben.annotations.NeedLogin;
import com.df.blueben.constant.NoteStateConstant;
import com.df.blueben.constant.enums.MediaTypeEnum;
import com.df.blueben.constant.enums.NoteStateEnum;
import com.df.blueben.constant.enums.VisibilityEnum;
import com.df.blueben.context.BaseContext;
import com.df.blueben.exception.BusinessException;
import com.df.blueben.exception.ErrorCode;
import com.df.blueben.model.dto.note.NoteAddDto;
import com.df.blueben.model.dto.note.NoteSearchDto;
import com.df.blueben.model.entity.*;
import com.df.blueben.model.vo.Note.NoteDetailVo;
import com.df.blueben.model.vo.Note.NoteVo;
import com.df.blueben.model.vo.PageVo;
import com.df.blueben.model.vo.user.UserSelectVo;
import com.df.blueben.service.*;
import com.df.blueben.mapper.NotesMapper;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* @author Administrator
* @description 针对表【notes】的数据库操作Service实现
* @createDate 2025-06-30 18:58:29
*/
@Service
@Slf4j
public class NotesServiceImpl extends ServiceImpl<NotesMapper, Notes>
    implements NotesService {

    private static final Integer PAGE_SIZE = 10;

    @Autowired
    NoteMediaService noteMediaService;

    @Autowired
    NoteTagsService noteTagsService;
    @Autowired
    TagsService tagsService;

    @Autowired
    UsersService usersService;

    @Autowired
    LikesService likesService;

    @Autowired
    TagsSelectAi tagsSelectAi;

    @Autowired
    FollowsService followsService;
    @Override
    @NeedLogin
    @Transactional
    public void addNote(NoteAddDto addDto) {
        validParam(addDto);
        Notes notes = new Notes();
        notes.setTitle(addDto.getTitle());
        notes.setContent(addDto.getContent());
        notes.setVisibility(addDto.getVisibility());
        Long userId = BaseContext.getCurrentId();
        notes.setUserId(userId);
        notes.setState(NoteStateConstant.PENDING_REVIEW);

        List<String> mediaUrls = addDto.getMediaUrls();
        notes.setCoverImageUrl(mediaUrls.getFirst());
        save(notes);
        List<NoteMedia> mediaList = new ArrayList<>();
        int order = 0;
        for (String mediaUrl : mediaUrls) {
            NoteMedia noteMedia = new NoteMedia();
            noteMedia.setMediaUrl(mediaUrl);
            noteMedia.setNoteId(notes.getId());
            noteMedia.setMediaType(addDto.getType());
            noteMedia.setSortOrder(order);
            order ++;
            mediaList.add(noteMedia);
        }
        noteMediaService.saveBatch(mediaList);
        //创建一个线程，来给该条笔记添加标签属性
        new Thread(() -> {
            List<Tags> tagsList = tagsService.lambdaQuery().list();
            Tags tags = tagsSelectAi.getTags(notes.getTitle(), notes.getContent(), tagsList);
            if(tags != null){
                //记录一下日志
                log.info("给笔记{}添加标签{}",notes.getId(),tags.getId());
                noteTagsService.save(new NoteTags(notes.getId(), tags.getId()));
            }
        }).start();
    }

    @Override
    public PageVo searchNotes(NoteSearchDto searchDto) {
        Integer tagId = searchDto.getTagId();
        Integer nextPage = searchDto.getNextPage();
        String searchText = searchDto.getSearchText();
        if(nextPage == null){
            nextPage = 1;
        }
        LambdaQueryWrapper<Notes> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.eq(Notes::getVisibility, VisibilityEnum.PUBLIC.getValue());
        lambdaWrapper.eq(Notes::getState, NoteStateEnum.AUDITING.getValue());
        PageVo pageVo = new PageVo();
        if(tagId == null || tagId == 0){
            //推荐逻辑
            // 1. 创建分页对象（当前页，每页数量）
            //TODO 后面实现推荐逻辑

            if(searchText != null){
                //根据note的内容或者note的标题来搜索
                lambdaWrapper.and(wrapper -> wrapper.like(Notes::getContent, searchText).or().like(Notes::getTitle, searchText));
            }
            List<NoteVo> noteVos = searchToNoteVo(lambdaWrapper, nextPage);
            pageVo.setContent(noteVos);
            pageVo.setNextPage(nextPage + 1);
        }else{
            //标签逻辑
            List<Long> noteIds = noteTagsService.lambdaQuery().eq(NoteTags::getTagId, tagId)
                    .list()
                    .stream()
                    .map(NoteTags::getNoteId)
                    .toList();
            lambdaWrapper.in(Notes::getId, noteIds);
            if(searchText != null){
                //根据note的内容或者note的标题来搜索
                lambdaWrapper.and(wrapper -> wrapper.like(Notes::getContent, searchText).or().like(Notes::getTitle, searchText));
            }
            // 开启分页
            List<NoteVo> noteVos = searchToNoteVo(lambdaWrapper,nextPage);
            pageVo.setContent(noteVos);
            pageVo.setNextPage(nextPage + 1);
        }
        return pageVo;
    }

    @Override
    public NoteDetailVo detailNote(Long id) {
        if(id == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"笔记id不能为空");
        }
        Notes note = getById(id);
        if(note == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"笔记不存在");
        }
        if(!Objects.equals(note.getState(), NoteStateEnum.AUDIT_PASS.getValue())){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"笔记不存在");
        }
        if(!Objects.equals(note.getVisibility(),VisibilityEnum.PUBLIC.getValue())){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"笔记不存在");
        }
        //查询笔记所属的用户
        Users user = usersService.getById(note.getUserId());

        NoteDetailVo noteDetailVo = new NoteDetailVo();
        UserSelectVo userSelectVo = new UserSelectVo();
        userSelectVo.setId(user.getId());
        userSelectVo.setAvatarUrl(user.getAvatarUrl());
        userSelectVo.setNickname(user.getNickname());
        userSelectVo.setBio(user.getBio());
        Long followedCount = followsService.lambdaQuery().eq(Follows::getFollowerId, user.getId()).count();
        userSelectVo.setFollowedCount(followedCount);
        Long followCount = followsService.lambdaQuery().eq(Follows::getFollowedId, user.getId()).count();
        userSelectVo.setFollowCount(followCount);

        noteDetailVo.setId(note.getId());
        noteDetailVo.setUserSelectVo(userSelectVo);
        noteDetailVo.setTitle(note.getTitle());
        noteDetailVo.setContent(note.getContent());
        noteDetailVo.setCoverImageUrl(note.getCoverImageUrl());
        noteDetailVo.setCreatedAt(note.getCreatedAt());

        return noteDetailVo;
    }

    List<NoteVo> searchToNoteVo(LambdaQueryWrapper<Notes> queryWrapper,Integer nextPage){
        PageHelper.startPage(nextPage == null ? 1:nextPage, PAGE_SIZE);
        List<Notes> notes = list(queryWrapper);
        return notes.stream().map(note -> {
            NoteVo noteVo = new NoteVo();
            noteVo.setId(note.getId());
            noteVo.setTitle(note.getTitle());
            noteVo.setCoverImageUrl(note.getCoverImageUrl());
            String avatarUrl = usersService.getById(note.getUserId()).getAvatarUrl();
            noteVo.setUserAvatarUrl(avatarUrl);
            Long count = likesService.lambdaQuery().eq(Likes::getNoteId, note.getId()).count();
            noteVo.setLikeCount(count);
            return noteVo;
        }).toList();
    }

    private void validParam(NoteAddDto addDto){
        if(addDto == null){
            throw new RuntimeException("笔记不能为空");
        }
        String title = addDto.getTitle();
        String content = addDto.getContent();
        Integer visibility = addDto.getVisibility();
        List<String> mediaUrls = addDto.getMediaUrls();
        Integer type = addDto.getType();
        if(VisibilityEnum.getVisibilityEnum(visibility) == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"笔记可见性设置错误");
        }
        if(MediaTypeEnum.getMediaTypeEnum(type) == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"笔记类型错误");
        }
        if(title == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"笔记标题不能为空");
        }
        if (content == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"笔记内容不能为空");
        }
        if(visibility == null){
            addDto.setVisibility(VisibilityEnum.PUBLIC.getValue());
        }
        if(mediaUrls ==null || mediaUrls.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"笔记图片或视频不能为空");
        }
        if(type == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"笔记类型不能为空");
        }
    }
}




